package vista.objetos;

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.util.Observable;

import javax.media.opengl.GL2;
import javax.swing.JFrame;
import javax.swing.JLabel;

import controlador.ContenedorDeErrores;


import eventos.EventoEtiquetaDeGraficable;

import vista.Tema;
import vista.geometria.Circulo;
import vista.paneles.hojaDibujo.HojaDeDibujo;
import vista.paneles.hojaDibujo.UtilHojaDeDibujo;
import vista.treeDiagrama.NodoTreeDiagrama;
import logica.Atributo;
import logica.ObjetoDiagrama;
import memento.IMemento;
import memento.MementoAtributoGraficable;

public abstract class AtributoGraficable extends GraficableConEtiqueta implements Identificable {
	
	private static final float RADIO_CIRCULO = 1.5f;

	private Atributo atributo;
	private Point puntoCentroEntidad = new Point();
	
	private static int MARGEN = 7;
	
	public AtributoGraficable(Atributo atributo)
	{
		this.atributo = atributo;
		inicializarEtiqueta(atributo);
	}

	private void inicializarEtiqueta(Atributo atributo)
	{
		String texto = atributo.getNombre();
		
		if ( this.atributo.getCardinalidadMin() != 1 || this.atributo.getCardinalidadMax() != 1 )
			texto += "(" + this.atributo.getCardinalidadMinString() + "," + this.atributo.getCardinalidadMaxString()+ ")";
		
		this.getEtiqueta().setText(texto);
		this.getEtiqueta().setSize(this.getEtiqueta().getMinimumSize());
		this.getEtiqueta().setVerticalAlignment(JLabel.CENTER);
	}
	
	@Override
	public ObjetoDiagrama getObjetoDiagramaDecorado() throws NoEsObjetoDiagramableException{
		throw new NoEsObjetoDiagramableException("Un AtribuoGraficable no decora un ObjetoDiagrama.");
	}
	
	@Override
	public NodoTreeDiagrama getNodoTreeDiagrama() throws NoEsObjetoNodoException {
		throw new NoEsObjetoNodoException("Un AtributoGraficable no puede agrearse al arbol.");
	}
	
	@Override
	public MouseAdapter getEventoEditarGraficable(JFrame ventanaPadre) {
		return null;
	}
	
	public Atributo getAtributo(){
		return atributo;
	}

	@Override
	public void update(Observable o, Object arg) {
	}
	
	@Override
	public void dragGraficable(Point desplazamiento) {
    	setUbicacionEtiquetaYPunto(desplazamiento.x, desplazamiento.y);
	}
	
	public void setPuntoCentroEntidad(Point punto){
		this.puntoCentroEntidad = punto;
	}
	
	private Point getPuntoCentroEntidad(){
		return this.puntoCentroEntidad;
	}
	
	@Override
	/*
	 * para el drag desde una relación o entidad. La posición de 
	 * Punto se mantiene en relación a la posición de la etiqueta
	 */
	public void setUbicacionEtiqueta(int dx, int dy) 
	{
		Point posicion = this.getEtiqueta().getLocation();

		super.setUbicacionEtiqueta(dx + posicion.x, dy + posicion.y);

		this.getPunto().translate(dx , dy);
	}
	
	public void setUbicacionEtiquetaYPunto(int dx, int dy) {
		
		Point posicion = this.getEtiqueta().getLocation();

		super.setUbicacionEtiqueta(dx + posicion.x, dy + posicion.y);
		
		int x = this.getEtiqueta().getLocation().x,
				y = this.getEtiqueta().getLocation().y;

        if ( x >= this.getPuntoCentroEntidad().x) {
            this.getPunto().setLocation(x - MARGEN, y + MARGEN);      
        }
        else {
        	this.getPunto().setLocation(x + MARGEN + getEtiqueta().getSize().width, y + MARGEN);
        }
	}
	
	// se llama al ppio, del pto sale la pos de la etiqueta
	public void setUbicacionCirculo()
	{
		int posX = this.getPunto().x,
				posY = this.getPunto().y;

        if ( posX >= this.getPuntoCentroEntidad().x) {
            super.setUbicacionEtiqueta(posX + MARGEN, posY - MARGEN);                             
        }
        else {
        	super.setUbicacionEtiqueta(posX - MARGEN - getEtiqueta().getSize().width, posY - MARGEN);
        }
	}
	
	@Override
	public boolean esElGraficableDe(ObjetoDiagrama objeto) {
		return false;
	}

	public boolean esElGraficableDe(Atributo atributo) {
		return this.getAtributo().equals(atributo); 
	}
	
	@Override
	protected EventoEtiquetaDeGraficable getEvento(HojaDeDibujo hoja) {
		return new EventoEtiquetaDeGraficable(hoja, this);
	}
	
	@Override
	public IMemento getMementoGenerico() {
		return new MementoAtributoGraficable(this);
	}
	
	@Override
	public boolean tieneLaEntidad(EntidadGraficable entidadGraficable) {
		return false;
	}
	
	@Override
	public boolean sePuedeBorrar(EntidadGraficable entidadGraficable) {
		return false;
	}
		
	@Override
	public void borrarseDeLaHoja()  {
		super.getContenedor().remove(this.getEtiqueta());
	}
	
	@Override
	public Point getPuntoInterseccion()
	{
		Point puntoMedio = new Point();
		
		puntoMedio.x = (3*this.getPunto().x + this.getPuntoCentroEntidad().x)/4;
		puntoMedio.y = (3*this.getPunto().y + this.getPuntoCentroEntidad().y)/4;
		
		return puntoMedio;
	}
	
	@Override
	public void dibujarse(Object areaDeDibujo)
	{
		GL2 gl = (GL2) areaDeDibujo;
		float[] centroAtributoMundo = UtilHojaDeDibujo.getCoordMundo(gl, this.getPunto().x, this.getPunto().y);
		
		gl.glPushMatrix();
			gl.glTranslatef(centroAtributoMundo[0], centroAtributoMundo[1], 0.0f);
			Circulo.dibujarCirculoRelleno(gl, RADIO_CIRCULO, 20.0f, Tema.getInstancia().getHojaColor());
			gl.glColor3fv(Tema.getInstancia().getAtributoColor());
			Circulo.dibujarCirculoContorno(gl, RADIO_CIRCULO, 20.0f);
		gl.glPopMatrix();
	}

	@Override
	public GraficableConEtiqueta copiarse(IContenedorDeGraficable contenedor) {
		return this.copiarse();
	}
	
	public abstract AtributoGraficable copiarse();
	
	@Override
	public void validar(ContenedorDeErrores errores) {
		
	}
}
